package com.bungarus.smart.busi;

import com.bungarus.busi.InnerClient;
import com.bungarus.model.BungarusClientException;
import com.bungarus.model.MessageBuilder;
import io.netty.channel.*;
import io.netty.handler.timeout.IdleStateEvent;
import org.apache.log4j.Logger;


public class ClientHeartbeatHandler extends ChannelInboundHandlerAdapter {
    Logger logger = Logger.getLogger(ClientHeartbeatHandler.class);

    private final Scanner scanner;
    private final String host;
    /**
     * How many times for retrying before timeout
     */
    private final int RETRY_LIMIT = 5;

    public ClientHeartbeatHandler(Scanner scanner, String host) {
        this.scanner = scanner;
        this.host = host;
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if(evt instanceof IdleStateEvent){
            sendPingMessage(ctx, RETRY_LIMIT);
        }
        else {
            super.userEventTriggered(ctx, evt);
        }
    }

    /**
     * Ping target server
     * @param ctx
     * @param retryLimit
     * @throws Exception
     */
    private void sendPingMessage(ChannelHandlerContext ctx, int retryLimit) throws Exception{
        ctx.writeAndFlush(MessageBuilder.buildHeartbeatPingMessage("smart"))
            .addListener(channelFuture -> {
                if(channelFuture.isSuccess()){
                    logger.debug("Ping message reached");
                }
                else{
                    logger.warn("Ping message is lost!");
                    if(retryLimit>0){
                        Thread.sleep(500);
                        sendPingMessage(ctx, retryLimit - 1);
                    }
                }
        });
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        logger.info("Server is offline -> " + host);
        this.scanner.removeRemoteChannel(host);
        super.channelInactive(ctx);
    }
}
